<?php

/**
 * Name: 头像生成服务
 * User: Silent
 * Date: 2025-11-17
 * Time: 17:30:00
 */

namespace App\Services\Avatar;

use Overtrue\Pinyin\Pinyin;
use Exception;

class AvatarGeneratorService
{
    protected $pinyin;
    protected $colors;

    public function __construct()
    {
        $this->pinyin = new Pinyin();

        // 定义一组美观的背景色
        $this->colors = [
            '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FECA57',
            '#FF9FF3', '#54A0FF', '#5F27CD', '#00D2D3', '#FF9F43',
            '#10AC84', '#EE5A24', '#0984E3', '#6C5CE7', '#A29BFE',
            '#FD79A8', '#E17055', '#00B894', '#00CEC9', '#74B9FF'
        ];
    }

    /**
     * 根据昵称生成头像
     *
     * @param string $nickname 昵称
     * @param int $size 头像尺寸，默认200x200
     * @return string|false 返回生成的图像数据，失败返回false
     */
    public function generateAvatar($nickname, $size = 200)
    {
        try {
            // 获取昵称的首字符
            $firstChar = $this->getFirstChar($nickname);

            // 根据昵称生成稳定的颜色
            $bgColor = $this->generateColor($nickname);
            $textColor = $this->getContrastColor($bgColor);

            // 创建图像
            $image = $this->createImage($size, $bgColor, $textColor, $firstChar);

            // 输出图像数据
            ob_start();
            imagepng($image);
            $imageData = ob_get_contents();
            ob_end_clean();

            // 释放内存
            imagedestroy($image);

            return $imageData;

        } catch (Exception $e) {
            \Log::error('头像生成失败', [
                'nickname' => $nickname,
                'error' => $e->getMessage()
            ]);
            return false;
        }
    }

    /**
     * 获取昵称的首字符
     *
     * @param string $nickname
     * @return string
     */
    protected function getFirstChar($nickname)
    {
        if (empty($nickname)) {
            return '?';
        }

        // 去除空格
        $nickname = trim($nickname);

        // 通过字节长度和字符长度比较判断是否包含中文
        if (mb_strlen($nickname, 'utf-8') == strlen($nickname)) {
            // 纯英文或数字，直接使用昵称
            $avatarStr = $nickname;
        } else {
            // 包含中文，转换为拼音首字母
            $avatarStr = $this->pinyin->abbr((string) $nickname);
        }

        return strtoupper(substr($avatarStr, 0, 1)) ?: '?';
    }

    /**
     * 根据昵称生成稳定的颜色
     *
     * @param string $nickname
     * @return string
     */
    protected function generateColor($nickname)
    {
        // 使用昵称的哈希值来确保同样的昵称总是生成相同的颜色
        $hash = md5($nickname);
        $index = hexdec(substr($hash, 0, 2)) % count($this->colors);

        return $this->colors[$index];
    }

    /**
     * 获取与背景色对比度高的文字颜色
     *
     * @param string $bgColor
     * @return array [r, g, b]
     */
    protected function getContrastColor($bgColor)
    {
        // 移除#号
        $bgColor = ltrim($bgColor, '#');

        // 转换为RGB
        $r = hexdec(substr($bgColor, 0, 2));
        $g = hexdec(substr($bgColor, 2, 2));
        $b = hexdec(substr($bgColor, 4, 2));

        // 计算亮度
        $brightness = ($r * 299 + $g * 587 + $b * 114) / 1000;

        // 根据背景亮度选择文字颜色
        return $brightness > 128 ? [0, 0, 0] : [255, 255, 255];
    }

    /**
     * 创建头像图像
     *
     * @param int $size 尺寸
     * @param string $bgColor 背景色
     * @param array $textColor 文字颜色 [r, g, b]
     * @param string $char 字符
     * @return resource 图像资源
     */
    protected function createImage($size, $bgColor, $textColor, $char)
    {
        // 创建画布
        $image = imagecreatetruecolor($size, $size);

        // 移除#号并转换背景色
        $bgColor = ltrim($bgColor, '#');
        $bgR = hexdec(substr($bgColor, 0, 2));
        $bgG = hexdec(substr($bgColor, 2, 2));
        $bgB = hexdec(substr($bgColor, 4, 2));

        $backgroundColor = imagecolorallocate($image, $bgR, $bgG, $bgB);
        $textColorResource = imagecolorallocate($image, $textColor[0], $textColor[1], $textColor[2]);

        // 填充背景
        imagefill($image, 0, 0, $backgroundColor);

        // 计算字体大小（基于图像大小）
        $fontSize = $size * 0.4;

        // 使用内置字体（如果需要更好的字体效果，可以使用TTF字体）
        $fontFile = $this->getSystemFont();

        if ($fontFile && file_exists($fontFile)) {
            // 使用TTF字体
            $bbox = imagettfbbox($fontSize, 0, $fontFile, $char);
            $textWidth = $bbox[4] - $bbox[0];
            $textHeight = $bbox[1] - $bbox[7];

            $x = ($size - $textWidth) / 2;
            $y = ($size - $textHeight) / 2 + $textHeight;

            imagettftext($image, $fontSize, 0, $x, $y, $textColorResource, $fontFile, $char);
        } else {
            // 使用内置字体
            $fontSize = 5; // 内置字体大小 1-5
            $textWidth = imagefontwidth($fontSize) * strlen($char);
            $textHeight = imagefontheight($fontSize);

            $x = ($size - $textWidth) / 2;
            $y = ($size - $textHeight) / 2;

            imagestring($image, $fontSize, $x, $y, $char, $textColorResource);
        }

        return $image;
    }

    /**
     * 获取系统字体路径
     *
     * @return string|null
     */
    protected function getSystemFont()
    {
        // 尝试常见的字体路径
        $fonts = [
            // Windows 系统字体
            'C:\Windows\Fonts\arial.ttf',
            'C:\Windows\Fonts\arialbd.ttf',
            'C:\Windows\Fonts\calibri.ttf',
            // Linux 系统字体
            '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf',
            '/usr/share/fonts/TTF/arial.ttf',
            '/System/Library/Fonts/Arial.ttf',
            // 项目资源字体（可以放置字体文件到项目中）
            resource_path('fonts/arial.ttf'),
            storage_path('fonts/arial.ttf')
        ];

        foreach ($fonts as $font) {
            if (file_exists($font)) {
                return $font;
            }
        }

        return null;
    }

    /**
     * 生成头像并保存为临时文件
     *
     * @param string $nickname
     * @param int $size
     * @return string|false 返回临时文件路径，失败返回false
     */
    public function generateAvatarFile($nickname, $size = 200)
    {
        $imageData = $this->generateAvatar($nickname, $size);

        if (!$imageData) {
            return false;
        }

        // 生成临时文件
        $tempFile = tempnam(sys_get_temp_dir(), 'avatar_') . '.png';

        if (file_put_contents($tempFile, $imageData) === false) {
            return false;
        }

        return $tempFile;
    }
}
